home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1988-08-16 | 17.3 KB | 662 lines |
- IMPLEMENTATION MODULE KermSend;
- (************************************************************************)
- (* Send one or more files to remote Kermit *)
- (* written: 10.10.85 Matthias Aebi *)
- (* last modification: 18.03.86 Matthias Aebi *)
- (************************************************************************)
-
- FROM Terminal IMPORT WriteString, WriteLn, Write;
- FROM OutTerminal IMPORT WriteC;
- FROM FileSystem IMPORT Lookup, Close, ReadChar, File, Response;
- FROM KermMisc IMPORT SendChar, AddBits, BitAND, BitOR, BitXOR,
- UnChar, ToChar, Ctl, PrtErrPacket, IncPackNum,
- DecPackNum, DispInit, DispFile, DispPack, DispTry,
- DispMsg;
- FROM KermParam IMPORT LBaudRate, LCheckType, LCurrPort, LEcho, LEOLChar,
- LEscChar, LFileType, LMaxRetries, LNumOfPad,
- LPackSize, LPadChar, LParity, LQuoteChar, LDebug,
- LStartChar, LTimeOut, LFilNamConv, REOLChar,
- RNumOfPad, RPackSize, RPadChar, RQuoteChar,
- RTimeOut, FileTyp, ParityTyp, Packet;
- FROM KermRecv IMPORT RecvPacket;
- FROM FileMessage IMPORT WriteResponse;
- FROM TextScreen IMPORT SetPos, ClearLines;
- FROM NameSearch IMPORT FindNames, NextName;
- FROM String IMPORT Insert, Delete, Length;
- FROM M2Kermit IMPORT Param1, Param2;
-
-
- CONST
- EOL = 36C;
- FF = 14C;
-
- VAR
- sendPack : Packet; (* globally defined local variables *)
- recvPack : Packet;
- num : CARDINAL;
- len : CARDINAL;
- typ : CHAR;
- theFile : File;
- msgNum : CARDINAL; (* Packet number *)
- numTry : CARDINAL; (* Number of retries *)
- fileOpen : BOOLEAN; (* File to send is already open *)
- size : CARDINAL; (* Size of the next data pack (0 = EOF) *)
-
-
- (************************************************************************)
- PROCEDURE BufFill(VAR buffer: Packet): CARDINAL;
- (************************************************************************)
- (* return the number of data characters written to buffer or 0 if EOF *)
- (* found *)
- VAR
- i : CARDINAL;
- ch : CHAR;
- ch7 : CHAR;
-
- BEGIN
- i := 0;
- LOOP
- IF i >= (LPackSize - 6) (* Seq, typ, Check1 -> 3 Bytes + 3 Bytes grow *)
- THEN
- EXIT;
- END;
-
- ReadChar(theFile, ch);
-
- IF theFile.eof
- THEN
- EXIT;
- END;
-
- ch7 := CHAR(BitAND(CARDINAL(ch),7FH));
-
- IF (ch7 < " ") OR (ch7 = CHR(127)) OR (ch7 = LQuoteChar)
- THEN
- IF (ch7 = EOL) AND (LFileType <> binary)
- THEN
- buffer[i] := LQuoteChar; INC(i);
- buffer[i] := Ctl(CHR(13)); INC(i);
- ch := CHR(10);
- ch7 := CHR(10);
- END;
- buffer[i] := LQuoteChar; INC(i);
- IF ch7 <> LQuoteChar
- THEN
- ch := Ctl(ch);
- ch7 := Ctl(ch7);
- END;
- END;
-
- IF (LFileType = binary)
- THEN
- buffer[i] := ch;
- ELSE
- buffer[i] := ch7;
- END;
- INC(i);
- END;
-
- RETURN(i);
- END BufFill;
-
-
- (************************************************************************)
- PROCEDURE SendPacket(type: CHAR; num, len: CARDINAL; data: ARRAY OF CHAR);
- (************************************************************************)
- VAR
- buffer : ARRAY [0..100] OF CHAR;
- chkSum : CARDINAL;
- i : CARDINAL;
- ch : CHAR;
-
- BEGIN
- IF LDebug (* if debugging on *)
- THEN
- SetPos(21,0);
- ClearLines(5);
-
- WriteString("Length: ");
- WriteC(len,2); WriteLn;
-
- WriteString("Number: ");
- WriteC(num,2); WriteLn;
-
- WriteString("Type: ");
- Write(type); WriteLn;
-
- WriteString("Packet: ");
- FOR i := 1 TO len DO
- Write(data[i-1]);
- END;
- END;
-
- FOR i:=1 TO LNumOfPad DO
- SendChar(LPadChar, LCurrPort);
- END;
-
- buffer[0] := LStartChar;
- buffer[1] := ToChar(len+3);
- chkSum := ORD(ToChar(len+3));
- buffer[2] := ToChar(num);
- chkSum := chkSum + ORD(ToChar(num));
- buffer[3] := type;
- chkSum := chkSum + ORD(type);
-
- i := 0;
- WHILE i < len DO
- buffer[i+4] := data[i];
- chkSum := chkSum + ORD(data[i]);
- INC(i);
- END;
-
- chkSum := BitAND(((BitAND(chkSum,192) DIV 64)+chkSum),63);
- buffer[len+4] := ToChar(chkSum);
-
- FOR i:=0 TO len+4 DO
- ch := buffer[i];
- CASE LParity OF
- none:
- ; |
-
- mark:
- ch := CHAR(BitOR(CARDINAL(ch),80H)); |
-
- space:
- ch := CHAR(BitAND(CARDINAL(ch),7FH)); |
-
- odd:
- IF NOT ODD(AddBits(ch))
- THEN
- ch := CHAR(BitOR(CARDINAL(ch),80H));
- END; |
-
- even:
- IF ODD(AddBits(ch))
- THEN
- ch := CHAR(BitOR(CARDINAL(ch),80H));
- END;
-
- END;
-
- SendChar(ch, LCurrPort);
- END;
-
- SendChar(REOLChar, LCurrPort); (* send EOL character *)
-
- END SendPacket;
-
-
- (************************************************************************)
- PROCEDURE SwitchSend(fileName, sendName: ARRAY OF CHAR): BOOLEAN;
- (************************************************************************)
- (* SwitchSend calls the different routines depending on the current send*)
- (* state. For a description of all states see Kermit protocol manual. *)
- (* Returns TRUE if send was successful. *)
-
- VAR
- state : CHAR; (* current send state *)
-
- (*------------------------------------------------------------------*)
- PROCEDURE ErrorExit(ErrMessage: ARRAY OF CHAR);
- (*------------------------------------------------------------------*)
- (* close file, display error message, send error packet *)
- BEGIN
- Close(theFile);
- fileOpen := FALSE;
-
- DispMsg(ErrMessage);
- SendPacket("E",0,Length(ErrMessage), ErrMessage);
- END ErrorExit;
-
-
-
- (*------------------------------------------------------------------*)
- PROCEDURE SendInit(VAR state: CHAR);
- (*------------------------------------------------------------------*)
- BEGIN
- INC(numTry);
- IF numTry > LMaxRetries
- THEN
- state := "T";
- RETURN;
- END;
-
- sendPack[0] := ToChar(LPackSize); (* Maximum packet lemgth *)
- sendPack[1] := ToChar(LTimeOut); (* seconds before timeot *)
- sendPack[2] := ToChar(LNumOfPad); (* number of padding char's *)
- sendPack[3] := Ctl(LPadChar); (* padding character *)
- sendPack[4] := ToChar(ORD(LEOLChar)); (* end of line/packet char *)
- sendPack[5] := LQuoteChar; (* control character quote *)
-
- SendPacket("S",msgNum,6,sendPack);
-
- RecvPacket(typ, num, len, recvPack);
- CASE typ OF
- "N":
- DispTry; | (* leave state unchanged *)
-
- "Y":
- IF num = msgNum
- THEN
- RPackSize := UnChar(recvPack[0]);
- RTimeOut := UnChar(recvPack[1]);
- RNumOfPad := UnChar(recvPack[2]);
- RPadChar := Ctl(recvPack[3]);
- REOLChar := CHR(UnChar(recvPack[4]));
- RQuoteChar := recvPack[5];
-
- IF ORD(REOLChar) = 0
- THEN
- REOLChar := 13C;
- END;
-
- IF ORD(RQuoteChar) = 0
- THEN
- RQuoteChar := "#";
- END;
-
- numTry := 0; (* reset try counter *)
- msgNum := IncPackNum(msgNum);
- DispPack;
- state := "F";
- END; |
-
- "E": (* got error packet *)
- PrtErrPacket(recvPack, len);
- state := "E"; |
-
- "T": (* timeout *)
- DispTry; |
-
- "A": (* user abort *)
- state := "A";
-
- ELSE (* undefined packet type *)
- state := "U";
-
- END;
-
- END SendInit;
-
-
- (*------------------------------------------------------------------*)
- PROCEDURE SendFile(VAR state: CHAR);
- (*------------------------------------------------------------------*)
- VAR
- i : CARDINAL;
- j : CARDINAL;
- ch : CHAR;
-
- BEGIN
- INC(numTry);
- IF numTry > LMaxRetries
- THEN
- state := "T";
- RETURN;
- END;
-
- IF NOT fileOpen
- THEN
- Lookup(theFile, fileName, FALSE);
- IF theFile.res <> done
- THEN
- DispMsg("Error on open file: ");
- WriteString(fileName); (* add filename & reason *)
- WriteResponse(theFile.res);
- Close(theFile);
- state := "E";
- RETURN;
- ELSE
- fileOpen := TRUE;
- END;
-
- IF LFilNamConv
- THEN
- Delete(fileName,0,3); (* strip device name *)
- END;
- END;
-
- i := 0; (* move file name to packet *)
- j := 0;
-
- IF sendName[0] # 0C
- THEN
- ch := sendName[i];
- ELSE
- ch := fileName[i];
- END;
-
- WHILE (ch <> 0C) AND (ch <> " ") DO
- IF LFilNamConv AND (sendName[0] = 0C)
- THEN
- IF (ch>="a") AND (ch<="z")
- THEN
- ch := CAP(ch);
- END;
-
- IF ((ch>="A") AND (ch<="Z")) OR
- ((ch>="0") AND (ch<="9")) OR
- (ch=".")
- THEN
- sendPack[j] := ch;
- INC(j);
- END;
- ELSE
- sendPack[j] := ch;
- INC(j);
- END;
- INC(i);
- IF sendName[0] # 0C
- THEN
- ch := sendName[i];
- ELSE
- ch := fileName[i];
- END;
- END;
-
- DispFile(fileName);
- IF sendName[0] # 0C
- THEN
- DispMsg("Sending as ");
- WriteString(sendName);
- sendName[0] := 0C; (* reset sendName *)
- END;
- SendPacket("F",msgNum,j,sendPack);
-
- RecvPacket(typ, num, len, recvPack);
- CASE typ OF
- "Y","N":
- IF typ = "N"
- THEN
- num := DecPackNum(num); (* NAK for msgNum+1 is the *)
- END; (* same as ACK for msgNum *)
-
- IF num = msgNum
- THEN
- numTry := 0;
- msgNum := IncPackNum(msgNum);
- size := BufFill(sendPack);
- state := "D";
- DispPack;
- ELSE
- DispTry;
- END; |
-
- "E": (* got error packet *)
- PrtErrPacket(recvPack, len);
- state := "E"; |
-
- "T": (* timeout *)
- DispTry; |
-
- "A": (* user abort *)
- state := "A";
-
- ELSE (* undefined packet type *)
- state := "U";
-
- END;
- END SendFile;
-
-
- (*------------------------------------------------------------------*)
- PROCEDURE SendData(VAR state: CHAR);
- (*------------------------------------------------------------------*)
- BEGIN
- INC(numTry);
- IF numTry > LMaxRetries
- THEN
- state := "T";
- RETURN;
- END;
-
- SendPacket("D",msgNum,size,sendPack);
-
- RecvPacket(typ, num, len, recvPack);
- CASE typ OF
- "Y","N":
- IF typ = "N"
- THEN
- num := DecPackNum(num); (* NAK for msgNum+1 is the *)
- END; (* same as ACK for msgNum *)
-
- IF num = msgNum
- THEN
- numTry := 0;
- msgNum := IncPackNum(msgNum);
- size := BufFill(sendPack);
- IF size = 0 (* -> EOF *)
- THEN
- state := "Z";
- END;
- DispPack;
- ELSE
- DispTry;
- END; |
-
- "E": (* got error packet *)
- PrtErrPacket(recvPack, len);
- state := "E"; |
-
- "T": (* timeout *)
- DispTry; |
-
- "A": (* user abort *)
- state := "A";
-
- ELSE (* undefined packet type *)
- state := "U";
-
- END;
-
- END SendData;
-
-
- (*------------------------------------------------------------------*)
- PROCEDURE SendEOF(VAR state: CHAR);
- (*------------------------------------------------------------------*)
- VAR
- foundOne : BOOLEAN;
- fileNo : CARDINAL;
- versionNo : CARDINAL;
- done : BOOLEAN;
-
- BEGIN
- INC(numTry);
- IF numTry > LMaxRetries
- THEN
- state := "T";
- RETURN;
- END;
-
- SendPacket("Z",msgNum,0,"");
-
- RecvPacket(typ, num, len, recvPack);
- CASE typ OF
- "Y","N":
- IF typ = "N"
- THEN
- num := DecPackNum(num); (* NAK for msgNum+1 is the *)
- END; (* same as ACK for msgNum *)
-
- IF num = msgNum
- THEN
- numTry := 0;
- msgNum := IncPackNum(msgNum);
- Close(theFile);
- fileOpen := FALSE;
- DispPack;
-
- NextName(foundOne, fileName, fileNo, versionNo);
- (* search next file *)
- Insert(fileName, 0, "DK."); (* add device name *)
-
- IF foundOne
- THEN
- state := "F";
- DispInit;
- ELSE
- state := "B";
- END;
-
- ELSE
- DispTry;
- END; |
-
- "E": (* got error packet *)
- PrtErrPacket(recvPack, len);
- state := "E"; |
-
- "T": (* timeout *)
- DispTry; |
-
- "A": (* user abort *)
- state := "A";
-
- ELSE (* undefined packet type *)
- state := "U";
-
- END;
-
- END SendEOF;
-
-
- (*------------------------------------------------------------------*)
- PROCEDURE SendBreak(VAR state: CHAR);
- (*------------------------------------------------------------------*)
- BEGIN
- INC(numTry);
- IF numTry > LMaxRetries
- THEN
- state := "T";
- RETURN;
- END;
-
- SendPacket("B",msgNum,0,"");
-
- RecvPacket(typ, num, len, recvPack);
- CASE typ OF
- "Y","N":
- IF typ = "N"
- THEN
- num := DecPackNum(num); (* NAK for msgNum+1 is the *)
- END; (* same as ACK for msgNum *)
-
- IF num = msgNum
- THEN
- numTry := 0;
- msgNum := IncPackNum(msgNum);
- state := "C";
- DispPack;
- ELSE
- DispTry;
- END; |
-
- "E": (* got error packet *)
- PrtErrPacket(recvPack, len);
- state := "E"; |
-
- "T": (* timeout *)
- DispTry; |
-
- "A": (* user abort *)
- state := "A";
-
- ELSE (* undefined packet type *)
- state := "U";
-
- END;
-
- END SendBreak;
-
-
- BEGIN (* SwitchSend *)
- msgNum := 0; (* First packet has # 0 *)
- numTry := 0; (* No retries so far *)
- DispInit;
- fileOpen := FALSE; (* no open file *)
- state := "S"; (* Send init is the start state *)
-
-
- LOOP
- CASE state OF
- "S":
- SendInit(state); |
-
- "F":
- SendFile(state); |
-
- "D":
- SendData(state); |
-
- "Z":
- SendEOF(state); |
-
- "B":
- SendBreak(state); |
-
- "C":
- RETURN TRUE; |
-
- "U":
- ErrorExit("Undefined packet type (M2-Kermit)");
- RETURN FALSE; |
-
- "T":
- ErrorExit("Too many retries (M2-Kermit)");
- RETURN FALSE; |
-
- "A":
- ErrorExit("User aborted transmission (M2-Kermit)");
- RETURN FALSE; |
-
- "E": (* Any other Problem *);
- Close(theFile);
- fileOpen := FALSE;
- RETURN FALSE;
-
- ELSE
- ErrorExit("Undefined state (M2-Kermit)");
- RETURN FALSE;
-
- END;
- END;
- END SwitchSend;
-
-
- (************************************************************************)
- PROCEDURE Send;
- (************************************************************************)
- CONST
- UpLowEqual = TRUE;
-
- VAR
- fileName : ARRAY [0..31] OF CHAR;
- foundOne : BOOLEAN;
- fileNo : CARDINAL;
- versionNo : CARDINAL;
-
- BEGIN
- IF Param1[0] = "?"
- THEN
- WriteString("Specify filename (including wildcards)");
- ELSE
- FindNames("DK", Param1, UpLowEqual);
- NextName(foundOne, fileName, fileNo, versionNo);
- Insert(fileName, 0, "DK."); (* add device name *)
-
- IF foundOne
- THEN
- IF SwitchSend(fileName, Param2)
- THEN
- DispMsg("Send successful");
- END;
- ELSE
- DispMsg("No file(s) found (Snd)");
- END;
- SetPos(27,0);
- END;
- END Send;
-
- END KermSend.
-